package com.lww.feature.test.stream;

import com.google.common.collect.Lists;
import org.junit.Test;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author yi an
 * @date 2017/3/24
 */
public class base {

    @Test
    public void testFilterAndMap() {
        List<Integer> integers = Arrays.asList(1, 2, 4, 5, 6, 7, 8, 9, 10);
        List<Integer> collect = integers.stream().filter(p -> p > 5).map(p -> p * 10).collect(Collectors.toList());
        System.out.println(collect);
    }

    @Test
    public void maptonull() {
        List<Integer> integers = Arrays.asList(1, 2, 4, 5, 6, 7, 8, 9, 10);
        List<Integer> collect = integers.stream().map(p -> mapToNull(p)).filter(p -> p != null).collect(Collectors.toList());
        System.out.println(collect);

    }

    public static Integer mapToNull(Integer integer) {
        return null;
    }

    //stream 要不要需不需要判断空
    @Test
    public void mapReduce() {
//        List<BigDecimal> bigDecimals = Arrays.asList(new BigDecimal("2"), new BigDecimal("1"), new BigDecimal("3"), null);
        List<BigDecimal> bigDecimals = new ArrayList<>();
        Optional<BigDecimal> reduce = bigDecimals.stream().filter(p -> p != null).reduce(BigDecimal::add);
        System.out.println(reduce.orElse(BigDecimal.ZERO));

    }

    //stream 要不要需不需要判断空
    @Test
    public void mapReduceListAddall() {
        List<Integer> integers = Lists.newArrayList(1, 2);
        List<Integer> integers2 = Lists.newArrayList(1, 2, 4);
        List<Integer> integers3 = Lists.newArrayList(1, 2, 9);
        List<List<Integer>> lists = Arrays.asList(integers, integers2, integers3);
        List<Integer> reduce1 = lists.stream().reduce((a, b) -> {
            a.addAll(b);
            return a;
        }).get();
        System.out.println(reduce1);

    }

    @Test
    public void groupingBy() {
        List<BigDecimal> bigDecimals = Arrays.asList(new BigDecimal("2"), new BigDecimal("1"), new BigDecimal("3"), null);
        List<BigDecimal> bigDecimals2 = Arrays.asList(new BigDecimal("1"), new BigDecimal("1"), new BigDecimal("3"), null);

    }

    @Test
    public void emprtyReduce() {

        List<BigDecimal> bigDecimals = null;
        try {
            bigDecimals.stream().reduce(BigDecimal::add);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<BigDecimal> bigDecimals2 = new ArrayList<>();

        try {
            BigDecimal bigDecimal = bigDecimals2.stream().reduce(BigDecimal::add).orElse(BigDecimal.TEN);
            System.out.println(bigDecimal);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {

            Map<Boolean, List<BigDecimal>> collect = bigDecimals2.stream().collect(Collectors.groupingBy(p -> p.compareTo(BigDecimal.ONE) > 0));
            Set<Map.Entry<Boolean, List<BigDecimal>>> entries = collect.entrySet();
            System.out.println(entries.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<BigDecimal> bigDecimals3 = Arrays.asList(new BigDecimal("1"), new BigDecimal("1"), new BigDecimal("3"), null);
        try {
            BigDecimal bigDecimal = bigDecimals3.stream().reduce(BigDecimal::add).orElse(BigDecimal.TEN);
            System.out.println(bigDecimal);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void reduce() {
        int value = Stream.of(1, 2, 3, 4).reduce(100, (sum, item) -> sum + item);
        System.out.println(value);

    }

    @Test
    public void groupBySum() {
        List<Foo> list = Arrays.asList(
                new Foo(1, "P1", new BigDecimal(300), new BigDecimal(400)),
                new Foo(2, "P2", new BigDecimal(600), new BigDecimal(400)),
                new Foo(3, "P3", new BigDecimal(30), new BigDecimal(20)),
                new Foo(3, "P3", new BigDecimal(70), new BigDecimal(20)),
                new Foo(1, "P1", new BigDecimal(360), new BigDecimal(40)),
                new Foo(4, "P4", new BigDecimal(320), new BigDecimal(200)),
                new Foo(4, "P4", new BigDecimal(500), new BigDecimal(900))
        );
        Map<Integer, Long> groupCount = list.stream()
                .collect(Collectors.groupingBy(foo -> foo.getId(), Collectors.counting()));
        groupCount.forEach((id, count) -> System.out.println(id + "\t" + count));
        Map<Integer, BigDecimal> groupBySum = list.stream()
                .collect(
                        Collectors.groupingBy(
                                Foo::getId, Collectors.reducing(BigDecimal.ZERO, Foo::getTargetCost, BigDecimal::add)
                        )
                );
        groupBySum.entrySet().forEach(p -> System.out.println(p.getKey() + ":" + p.getValue()));

        list.stream().collect(Collectors.groupingBy(
                Foo::getId, Collectors.reducing(
                        (a, b) -> new Foo(a.getId(), a.getName(), a.getTargetCost().add(b.getTargetCost()), a.getActualCost().add(b.getActualCost()))
                )
        )).entrySet().forEach(p -> System.out.println(p.getValue().toString()));


        list.stream().collect(Collectors.groupingBy(
                p->p.getId()<3, Collectors.reducing(
                        (a, b) -> new Foo(a.getId(), a.getName(), a.getTargetCost().add(b.getTargetCost()), a.getActualCost().add(b.getActualCost()))
                )
        )).entrySet().forEach(p -> System.out.println(p.getValue().toString()));
        Collections.sort(list,(p1,p2)->p2.getTargetCost().compareTo(p1.getTargetCost()));

    }


    @Test
    public void toTest() {
        List<Foo> list = Arrays.asList(
                new Foo(1, "P1", new BigDecimal(300), new BigDecimal(400)),
                new Foo(2, "P2", new BigDecimal(600), new BigDecimal(400)),
                new Foo(3, "P3", new BigDecimal(30), new BigDecimal(20))
        );
        //key重复会报下面的错误
        // java.lang.IllegalStateException: Duplicate key {  "id":3, "name":"P3", "targetCost":30, "actualCost":20}

        Map<Integer, Foo> integerFooMap = list.stream().collect(Collectors.toMap(Foo::getId, Function.identity()));
        integerFooMap.get(1);

        Map<Integer, String> collect = list.stream().collect(Collectors.toMap(Foo::getId, Foo::getName));
        collect.get(1);


    }
    @Test
    public void groupByMul() {
        List<Foo> list = Arrays.asList(
                new Foo(1, "P1", new BigDecimal(300), new BigDecimal(400)),
                new Foo(1, "P1", new BigDecimal(600), new BigDecimal(400)),
                new Foo(1, "P3", new BigDecimal(30), new BigDecimal(20)),
                new Foo(2, "P3", new BigDecimal(70), new BigDecimal(20)),
                new Foo(2, "P3", new BigDecimal(360), new BigDecimal(40)),
                new Foo(2, "P3", new BigDecimal(320), new BigDecimal(200)),
                new Foo(4, "P4", new BigDecimal(500), new BigDecimal(900))
        );
        Map<Integer, Long> groupCount = list.stream()
                .collect(Collectors.groupingBy(foo -> foo.getId(), Collectors.counting()));
        groupCount.forEach((id, count) -> System.out.println(id + "\t" + count));
        Map<Integer, Map<String, BigDecimal>> collect = list.stream()
                .collect(
                        Collectors.groupingBy(
                                Foo::getId, Collectors.groupingBy(Foo::getName, Collectors.reducing(BigDecimal.ZERO, Foo::getTargetCost, BigDecimal::add))
                        )
                );

        ArrayList<Foo> foos = new ArrayList<>();
        collect.entrySet().forEach(
                p->p.getValue().entrySet().forEach(pp->foos.add(new Foo(p.getKey(),pp.getKey(),pp.getValue(),BigDecimal.ZERO)))
        );
        System.out.println(foos.size());
        collect.get(1);

    }
}
